#include <linux/module.h>
#include <linux/pci.h>
#include <linux/fs.h>
#include <linux/device.h>
#include <linux/uaccess.h>
#include <linux/io.h>
#include <linux/slab.h>
#include <linux/wait.h>
#include <linux/poll.h>
#include <linux/msi.h>
#include <linux/mutex.h>
#include <linux/cdev.h>
#include <linux/interrupt.h>
#include <linux/workqueue.h>
#include <linux/version.h>
#include "drv_ai.h"

#define AI_CMD_CODE_MASK        0x0000FFFF      /* AI 指令码 掩码 */
#define AI_CMD_CODE_SHIFT       0               /* AI 指令码 偏移 */

#define AI_RANGE_MASK           0x03            /* AI 量程掩码 */
#define AI_RANGE_10V_LSB        305             /* 305uV */
#define AI_RANGE_2V5_LSB        76              /* 76uV */
#define AI_RANGE_5V_LSB         152             /* 152uV */
#define AI_DEF_RANGE            AI_RANGE_10V    /* AI 默认量程, 0: ±10V, 1: ±2.5V, 2: ±5V, 3: ±10V */

#define AI_MODE_MASK            0x00380000      /* AI 模式掩码 */
#define AI_OSR_MASK             0x00070000      /* AI 过采样掩码 */
#define AI_SAMPLE_MASK          0x0000FFFF      /* AI 采样间隔掩码 */
#define AI_MODE_SHIFT           19              /* AI 模式偏移 */
#define AI_OSR_SHIFT            16              /* AI 过采样偏移 */
#define AI_SAMPLE_SHIFT         0               /* AI 采样间隔偏移 */
#define AI_US_TO_HZ             1000000         /* AI us 转换到 Hz */
#define AI_DEF_MODE             AI_MOD_SMP      /* AI 默认模式 */
#define AI_DEF_OSR              0               /* AI 默认过采样, 0, 2, 4, 8, 16, 32, 64, 128 */
#define AI_DEF_SAMPLE           100000          /* AI 默认采样率, 1~100000Hz */

#define AI_MSI_MASK             0x01            /* AI MSI 掩码 */
#define AI_DMA_MSI_MASK         0x02            /* AI DMA MSI 掩码 */
#define AI_DMA_MSI_VEC          0               /* AI DMA MSI 中断向量 */
#define AI_TIM_MSI_VEC          18              /* AI TIM MSI 中断向量 */

#define AI_ID_MASK              0xFF000000      /* AI 通道掩码 */
#define AI_DATA_MASK            0x00FFFFFF      /* AI 数据掩码 */
#define AI_DATA_SIGN_MASK       0x0080000       /* AI 数据符号位掩码 */
#define AI_ID_SHIFT             24              /* AI 通道偏移 */
#define AI_DATA_SHIFT           0               /* AI 数据偏移 */

#define AI_DEF_DMA_SIZE         (64 * 1024)     /* AI DMA 大小 128KByte */

#define AI_SAMP_TIM_MASK        0xFFFF0000      /* AI 抽样定时间隔时间掩码 */
#define AI_SLID_WIN_MASK        0x0000FFFF      /* AI 滑动平均窗口掩码 */
#define AI_SAMP_TIM_SHIFT       16              /* AI 抽样定时间隔时间偏移 */
#define AI_SLID_WIN_SHIFT       0               /* AI 滑动平均窗口偏移 */
#define AI_DEF_SAMP_TIM         65535           /* AI 默认抽样定时间隔, 0~65535us */
#define AI_DEF_SLID_WIN         1               /* AI 默认滑动平均窗口, 1~32 个 */

/* AI 寄存器*/
enum ai_reg_t {
    AI_VERSION_OFFSET           = 0x04,         /* AI 版本寄存器偏移 */
    AI_CMD_OFFSET               = 0x08,         /* AI 指令寄存器偏移 */
    AI_CH_VAL_OFFSET            = 0x38,         /* AI 通道数据寄存器偏移*/
    AI_RANGE_OFFSET             = 0x44,         /* AI 范围寄存器偏移 */
    AI_MODE_OSR_SMP_OFFSET      = 0x48,         /* AI 模式、过采样和采样间隔寄存器偏移 */
    AI_MSI_MASK_OFFSET          = 0x60,         /* AI MSI 中断屏蔽寄存器偏移 */
    AI_DMA_LENGTH_OFFSET        = 0x68,         /* AI DMA 大小寄存器偏移 */
    AI_SAMP_SLID_WIN_OFFSET     = 0x80,         /* AI 抽样定时间隔时间、滑动平均窗口寄存器偏移 */
};

/* 文件操作函数声明 */
static int open_ai(struct inode *inode, struct file *filp);
static int release_ai(struct inode *inode, struct file *filp);
static ssize_t read_ai(struct file *filp, char __user *buf, 
                       size_t count, loff_t *ppos);
static ssize_t write_ai(struct file *filp, const char __user *buf, 
                        size_t count, loff_t *ppos);
static long ioctl_ai(struct file *filp, unsigned int cmd, 
                     unsigned long arg);

/* 文件操作结构体 */
static const struct file_operations cdev_fops = {
    .owner = THIS_MODULE,
    .open = open_ai,
    .release = release_ai,
    .read = read_ai,
    .write = write_ai,
    .unlocked_ioctl = ioctl_ai,
    .poll = NULL,
    .llseek = no_llseek,
};

/* 读取 AI 寄存器 */
static u32 read_ai_reg_le(struct pcie_dev_t *pcie_dev, u32 reg)
{
    u32 val = 0;
    unsigned long flags = 0;    /* 用于保存中断状态 */

    /* 获取自旋锁(保存中断状态) */
    spin_lock_irqsave(&pcie_dev->splock, flags);
    val = ioread32(pcie_dev->bar[0] + reg);
    /* 释放自旋锁(恢复中断状态) */
    spin_unlock_irqrestore(&pcie_dev->splock, flags);
    pr_debug("%s  reg=0x%08x, val=0x%08x", __func__, reg, val);

    return val;
}

/* 写入 AI 寄存器 */
static void write_ai_reg_le(struct pcie_dev_t *pcie_dev, u32 reg, u32 val)
{
    unsigned long flags = 0;    /* 用于保存中断状态 */

    /* 获取自旋锁(保存中断状态) */
    spin_lock_irqsave(&pcie_dev->splock, flags);
    iowrite32(val, pcie_dev->bar[0] + reg);
    /* 释放自旋锁(恢复中断状态) */
    spin_unlock_irqrestore(&pcie_dev->splock, flags);
    pr_debug("%s reg=0x%08x, val=0x%08x", __func__, reg, val);
}

/* 使能 MSI 中断 */
static int enable_ai_msi_irq(struct ai_ctrl_t *pctrl)
{
    u32 val = 0;

    /* 获取互斥锁 */
    if (mutex_lock_interruptible(&pctrl->lock)) {
        dev_err(pctrl->dev, "Acquire %s %s mutex failed", __func__, pctrl->name);
        return -ERESTARTSYS;
    }
    val = pctrl->read_reg(pctrl->pcie_dev, AI_MSI_MASK_OFFSET);
    val |= AI_MSI_MASK;
    pctrl->write_reg(pctrl->pcie_dev, AI_MSI_MASK_OFFSET, val);
    pr_debug("%s success", __func__);
    /* 释放互斥锁 */
    mutex_unlock(&pctrl->lock);

    return 0;
}

/* 禁用 MSI 中断 */
static int disable_ai_msi_irq(struct ai_ctrl_t *pctrl)
{
    u32 val = 0;

    /* 获取互斥锁 */
    if (mutex_lock_interruptible(&pctrl->lock)) {
        dev_err(pctrl->dev, "Acquire %s %s mutex failed", __func__, pctrl->name);
        return -ERESTARTSYS;
    }
    val = pctrl->read_reg(pctrl->pcie_dev, AI_MSI_MASK_OFFSET);
    val &= (~AI_MSI_MASK);
    pctrl->write_reg(pctrl->pcie_dev, AI_MSI_MASK_OFFSET, val);
    pr_debug("%s success", __func__);
    /* 释放互斥锁 */
    mutex_unlock(&pctrl->lock);

    return 0;
}

// /* 使能 DMA MSI 中断 */
// static int enable_ai_dma_msi_irq(struct ai_ctrl_t *pctrl)
// {
//     u32 val = 0;

//     /* 获取互斥锁 */
//     if (mutex_lock_interruptible(&pctrl->lock)) {
//         dev_err(pctrl->dev, "Acquire %s %s mutex failed", __func__, pctrl->name);
//         return -ERESTARTSYS;
//     }
//     val = pctrl->read_reg(pctrl->pcie_dev, AI_MSI_MASK_OFFSET);
//     val |= AI_DMA_MSI_MASK;
//     pctrl->write_reg(pctrl->pcie_dev, AI_MSI_MASK_OFFSET, val);
//     pr_debug("%s success", __func__);
//     /* 释放互斥锁 */
//     mutex_unlock(&pctrl->lock);

//     return 0;
// }

// /* 禁用 DMA MSI 中断 */
// static int disable_ai_dma_msi_irq(struct ai_ctrl_t *pctrl)
// {
//     u32 val = 0;

//     /* 获取互斥锁 */
//     if (mutex_lock_interruptible(&pctrl->lock)) {
//         dev_err(pctrl->dev, "Acquire %s %s mutex failed", __func__, pctrl->name);
//         return -ERESTARTSYS;
//     }
//     val = pctrl->read_reg(pctrl->pcie_dev, AI_MSI_MASK_OFFSET);
//     val &= (~AI_DMA_MSI_MASK);
//     pctrl->write_reg(pctrl->pcie_dev, AI_MSI_MASK_OFFSET, val);
//     pr_debug("%s success", __func__);
//     /* 释放互斥锁 */
//     mutex_unlock(&pctrl->lock);

//     return 0;
// }

/* 开始 AI 采集 */
static void start_ai_nolock(struct ai_ctrl_t *pctrl)
{
    pctrl->cmd = AI_CMD_START;
    pctrl->write_reg(pctrl->pcie_dev, AI_CMD_OFFSET, AI_CMD_START);
    dev_dbg(pctrl->dev, "Start AI success");
}

/* 停止 AI 采集 */
static void stop_ai_nolock(struct ai_ctrl_t *pctrl)
{
    pctrl->cmd = AI_CMD_STOP;
    pctrl->write_reg(pctrl->pcie_dev, AI_CMD_OFFSET, AI_CMD_STOP);
    dev_dbg(pctrl->dev, "Stop AI success");
}

/* 配置 AI 参数 */
static void config_ai_nolock(struct ai_ctrl_t *pctrl)
{
    pctrl->cmd = AI_CMD_CONFIG;
    pctrl->write_reg(pctrl->pcie_dev, AI_CMD_OFFSET, AI_CMD_CONFIG);
    dev_dbg(pctrl->dev, "Config AI success");
}

/* 配置 AI 模式 */
static int set_ai_mode(struct ai_ctrl_t *pctrl, u8 mode)
{
    u8 mode_code = mode;
    u32 val = 0;

    /* 获取互斥锁 */
    if (mutex_lock_interruptible(&pctrl->lock)) {
        dev_err(pctrl->dev, "Acquire %s %s mutex failed", __func__, pctrl->name);
        return -ERESTARTSYS;
    }
    switch (mode) {
    case AI_MOD_SMP:
    case AI_MOD_SMP_TIM:
        break;
    case AI_MOD_RAW_DMA:
        /* 初始化 PCIe DMA */
        init_pcie_dma(&pctrl, pctrl->dev, &pctrl->dma, pctrl->pcie_dev->bar[1]);
        init_waitqueue_head(&pctrl->dma.wq_frame);      /* 初始化等待队列（数据帧完成） */
        dev_info(pctrl->dev, "DMA memory allocated: alloc_virt=%p, alloc_phys=0x%0llx, size=%zu",
                 pctrl->dma.alloc_virt, (unsigned long long)pctrl->dma.alloc_phys, pctrl->dma.pl_size);
        break;
    case AI_MOD_RAW:
        break;
    default:
        mode_code = AI_DEF_MODE;
        dev_warn(pctrl->dev, "AI mode %d not support, use default %d", mode, mode_code);
        break;
    }
    pctrl->mode = mode_code;
    val = pctrl->read_reg(pctrl->pcie_dev, AI_MODE_OSR_SMP_OFFSET);
    val &= (~AI_MODE_MASK);
    val |= (mode_code << AI_MODE_SHIFT);
    pctrl->write_reg(pctrl->pcie_dev, AI_MODE_OSR_SMP_OFFSET, val);
    dev_dbg(pctrl->dev, "Set AI mode %d success", mode_code);
    /* 配置 AI 参数 */
    config_ai_nolock(pctrl);
    /* 释放互斥锁 */
    mutex_unlock(&pctrl->lock);

    return 0;
}

/* 获取 AI 模式 */
static int get_ai_mode(struct ai_ctrl_t *pctrl)
{
    int ret = 0;
    u32 val = 0; 

    /* 获取互斥锁 */
    if (mutex_lock_interruptible(&pctrl->lock)) {
        dev_err(pctrl->dev, "Acquire %s %s mutex failed", __func__, pctrl->name);
        return -ERESTARTSYS;
    }
    val = pctrl->read_reg(pctrl->pcie_dev, AI_MODE_OSR_SMP_OFFSET);
    pctrl->chk_mode = ((val & AI_MODE_MASK) >> AI_MODE_SHIFT);
    if (pctrl->chk_mode != pctrl->mode) {
        dev_err(pctrl->dev, "Get AI mode %d, not the set %d", pctrl->chk_mode, pctrl->mode);
        ret = -EFAULT;
        goto unlock;
    } else {
        switch (pctrl->chk_mode) {
        case AI_MOD_SMP:
        case AI_MOD_SMP_TIM:
        case AI_MOD_RAW_DMA:
        case AI_MOD_RAW:
            dev_dbg(pctrl->dev, "Get AI mode %d, is the set %d", pctrl->chk_mode, pctrl->mode);
            break;
        default:
            dev_err(pctrl->dev, "Get AI mode %d not support", pctrl->chk_mode);
            ret = -EFAULT;
            goto unlock;
        }
    }

unlock:
    /* 释放互斥锁 */
    mutex_unlock(&pctrl->lock);

    return ret;
}

/* 配置 AI 过采样 */
static int set_ai_osr(struct ai_ctrl_t *pctrl, u8 osr)
{
    u8 osr_code = osr;
    u32 val = 0;

    /* 获取互斥锁 */
    if (mutex_lock_interruptible(&pctrl->lock)) {
        dev_err(pctrl->dev, "Acquire %s %s mutex failed", __func__, pctrl->name);
        return -ERESTARTSYS;
    }
    switch (osr) {
    case AI_OSR_0:
    case AI_OSR_2:
    case AI_OSR_4:
    case AI_OSR_8:
    case AI_OSR_16:
    case AI_OSR_32:
    case AI_OSR_64:
    case AI_OSR_128:
        break;
    default:
        osr_code = AI_DEF_OSR;
        dev_warn(pctrl->dev, "AI OSR %d not support, use default %d", osr, osr_code);
        break;
    }
    pctrl->osr = osr_code;
    val = pctrl->read_reg(pctrl->pcie_dev, AI_MODE_OSR_SMP_OFFSET);
    val &= (~AI_OSR_MASK);
    val |= ((osr_code << AI_OSR_SHIFT) & AI_OSR_MASK);
    pctrl->write_reg(pctrl->pcie_dev, AI_MODE_OSR_SMP_OFFSET, val);
    dev_dbg(pctrl->dev, "Set AI OSR %d success", osr);
    /* 配置 AI 参数 */
    config_ai_nolock(pctrl);
    /* 释放互斥锁 */
    mutex_unlock(&pctrl->lock);

    return 0;
}

/* 获取 AI 过采样 */
static int get_ai_osr(struct ai_ctrl_t *pctrl)
{
    int ret = 0;
    u32 val = 0;

    /* 获取互斥锁 */
    if (mutex_lock_interruptible(&pctrl->lock)) {
        dev_err(pctrl->dev, "Acquire %s %s mutex failed", __func__, pctrl->name);
        return -ERESTARTSYS;
    }
    val = pctrl->read_reg(pctrl->pcie_dev, AI_MODE_OSR_SMP_OFFSET);
    pctrl->chk_osr = ((val & AI_OSR_MASK) >> AI_OSR_SHIFT);
    if (pctrl->chk_osr != pctrl->osr) {
        dev_err(pctrl->dev, "Get AI OSR %d, not the set %d", pctrl->chk_osr, pctrl->osr);
        ret = -EFAULT;
        goto unlock;
    } else {
        switch (pctrl->chk_osr) {
        case AI_OSR_0:
        case AI_OSR_2:
        case AI_OSR_4:
        case AI_OSR_8:
        case AI_OSR_16:
        case AI_OSR_32:
        case AI_OSR_64:
        case AI_OSR_128:
            dev_dbg(pctrl->dev, "Get AI OSR %d, is the set %d", pctrl->chk_osr, pctrl->osr);
            break;
        default:
            dev_err(pctrl->dev, "Get AI OSR %d not support", pctrl->chk_osr);
            ret = -EFAULT;
            goto unlock;
        }
    }

unlock:
    /* 释放互斥锁 */
    mutex_unlock(&pctrl->lock);

    return ret;
}

/* 配置 AI 采样率 */
static int set_ai_samp_rate(struct ai_ctrl_t *pctrl, u32 rate)
{
    u32 val = 0;

    /* 获取互斥锁 */
    if (mutex_lock_interruptible(&pctrl->lock)) {
        dev_err(pctrl->dev, "Acquire %s %s mutex failed", __func__, pctrl->name);
        return -ERESTARTSYS;
    }
    pctrl->samp_rate = rate;
    pctrl->interval = AI_US_TO_HZ / pctrl->samp_rate;       /* Hz to us*/
    val = pctrl->read_reg(pctrl->pcie_dev, AI_MODE_OSR_SMP_OFFSET);
    val &= (~AI_SAMPLE_MASK);
    val |= ((pctrl->interval << AI_SAMPLE_SHIFT) & AI_SAMPLE_MASK);
    pctrl->write_reg(pctrl->pcie_dev, AI_MODE_OSR_SMP_OFFSET, val);
    dev_dbg(pctrl->dev, "Set AI sample rate %dus %dHz success", pctrl->interval, pctrl->samp_rate);
    /* 配置 AI 参数 */
    config_ai_nolock(pctrl);
    /* 释放互斥锁 */
    mutex_unlock(&pctrl->lock);

    return 0;
}

/* 获取 AI 采样率 */
static int get_ai_samp_rate(struct ai_ctrl_t *pctrl)
{
    int ret = 0;
    u32 val = 0;

    /* 获取互斥锁 */
    if (mutex_lock_interruptible(&pctrl->lock)) {
        dev_err(pctrl->dev, "Acquire %s %s mutex failed", __func__, pctrl->name);
        return -ERESTARTSYS;
    }
    val = pctrl->read_reg(pctrl->pcie_dev, AI_MODE_OSR_SMP_OFFSET);
    pctrl->chk_interval = ((val & AI_SAMPLE_MASK) >> AI_SAMPLE_SHIFT);
    pctrl->chk_samp_rate = AI_US_TO_HZ / pctrl->chk_interval;       /* us to Hz*/
    if (pctrl->chk_interval != pctrl->interval || 
        pctrl->chk_samp_rate != pctrl->samp_rate) {
        dev_err(pctrl->dev, "Get AI sample rate %dus %dHz, not the set %dus %dHz", 
                pctrl->chk_interval, pctrl->chk_samp_rate, pctrl->interval, pctrl->samp_rate);
        ret = -EFAULT;
        goto unlock;
    } else {
        dev_dbg(pctrl->dev, "Get AI sample rate %dus %dHz, is the set %dus %dHz", 
                pctrl->chk_interval, pctrl->chk_samp_rate, pctrl->interval, pctrl->samp_rate);
    }

unlock:
    /* 释放互斥锁 */
    mutex_unlock(&pctrl->lock);

    return ret;
}

/* 配置 AI 抽样定时间隔 */
static int set_ai_samp_tim(struct ai_ctrl_t *pctrl, u16 samp_tim)
{
    u32 val = 0;

    /* 获取互斥锁 */
    if (mutex_lock_interruptible(&pctrl->lock)) {
        dev_err(pctrl->dev, "Acquire %s %s mutex failed", __func__, pctrl->name);
        return -ERESTARTSYS;
    }
    pctrl->samp_tim = samp_tim;
    val = pctrl->read_reg(pctrl->pcie_dev, AI_SAMP_SLID_WIN_OFFSET);
    val &= (~AI_SAMP_TIM_MASK);
    val |= (samp_tim << AI_SAMP_TIM_SHIFT);
    pctrl->write_reg(pctrl->pcie_dev, AI_SAMP_SLID_WIN_OFFSET, val);
    dev_dbg(pctrl->dev, "Set AI sample time %dus success", samp_tim);
    /* 配置 AI 参数 */
    config_ai_nolock(pctrl);
    /* 释放互斥锁 */
    mutex_unlock(&pctrl->lock);

    return 0;
}

/* 获取 AI 抽样定时间隔 */
static int get_ai_samp_tim(struct ai_ctrl_t *pctrl)
{
    int ret = 0;
    u32 val = 0;

    /* 获取互斥锁 */
    if (mutex_lock_interruptible(&pctrl->lock)) {
        dev_err(pctrl->dev, "Acquire %s %s mutex failed", __func__, pctrl->name);
        return -ERESTARTSYS;
    }
    val = pctrl->read_reg(pctrl->pcie_dev, AI_SAMP_SLID_WIN_OFFSET);
    pctrl->chk_samp_tim = ((val & AI_SAMP_TIM_MASK) >> AI_SAMP_TIM_SHIFT);
    if (pctrl->chk_samp_tim != pctrl->samp_tim) {
        dev_err(pctrl->dev, "Get AI sample time %d, not the set %d", 
                pctrl->chk_samp_tim, pctrl->samp_tim);
        ret = -EFAULT;
        goto unlock;
    } else {
        dev_dbg(pctrl->dev, "Get AI sample time %d, is the set %d", 
                pctrl->chk_samp_tim, pctrl->samp_tim);
    }

unlock:
    /* 释放互斥锁 */
    mutex_unlock(&pctrl->lock);

    return ret;
}

/* 配置 AI 滑动平均窗口 */
static int set_ai_slid_win(struct ai_ctrl_t *pctrl, u16 slid_win)
{
    u32 val = 0;

    /* 获取互斥锁 */
    if (mutex_lock_interruptible(&pctrl->lock)) {
        dev_err(pctrl->dev, "Acquire %s %s mutex failed", __func__, pctrl->name);
        return -ERESTARTSYS;
    }
    pctrl->slid_win = slid_win;
    val = pctrl->read_reg(pctrl->pcie_dev, AI_SAMP_SLID_WIN_OFFSET);
    val &= (~AI_SLID_WIN_MASK);
    val |= (slid_win << AI_SLID_WIN_SHIFT);
    pctrl->write_reg(pctrl->pcie_dev, AI_SAMP_SLID_WIN_OFFSET, val);
    dev_dbg(pctrl->dev, "Set AI slide window %d success", slid_win);
    /* 配置 AI 参数 */
    config_ai_nolock(pctrl);
    /* 释放互斥锁 */
    mutex_unlock(&pctrl->lock);

    return 0;
}

/* 获取 AI 滑动平均窗口 */
static int get_ai_slid_win(struct ai_ctrl_t *pctrl)
{
    int ret = 0;
    u32 val = 0;

    /* 获取互斥锁 */
    if (mutex_lock_interruptible(&pctrl->lock)) {
        dev_err(pctrl->dev, "Acquire %s %s mutex failed", __func__, pctrl->name);
        return -ERESTARTSYS;
    }
    val = pctrl->read_reg(pctrl->pcie_dev, AI_SAMP_SLID_WIN_OFFSET);
    pctrl->chk_slid_win = ((val & AI_SLID_WIN_MASK) >> AI_SLID_WIN_SHIFT);
    if (pctrl->chk_slid_win != pctrl->slid_win) {
        dev_err(pctrl->dev, "Get AI slide window %d, not the set %d", 
                pctrl->chk_slid_win, pctrl->slid_win);
        ret = -EFAULT;
        goto unlock;
    } else {
        dev_dbg(pctrl->dev, "Get AI slide window %d, is the set %d", 
                pctrl->chk_slid_win, pctrl->slid_win);
    }

unlock:
    /* 释放互斥锁 */
    mutex_unlock(&pctrl->lock);

    return ret;
}

/* 配置 AI 量程 */
static int set_ai_range(struct ai_dev_t *pdev, u8 range)
{
    struct ai_ctrl_t *pctrl = (struct ai_ctrl_t *)(pdev->parent);
    u8 range_code = range;
    u32 val = 0;

    switch (range) {
    case AI_RANGE_2V5:
        dev_dbg(pdev->dev, "Set AI%d range %s", pdev->index, "2.5V");
        break;
    case AI_RANGE_5V:
        dev_dbg(pdev->dev, "Set AI%d range %s", pdev->index, "5V");
        break;
    case AI_RANGE_10V0:
    case AI_RANGE_10V:
        dev_dbg(pdev->dev, "Set AI%d range %s", pdev->index, "10V");
        break;
    default:
        dev_warn(pdev->dev, "AI%d range %d not support, use default %s", pdev->index, range, "10V");
        range_code = AI_DEF_RANGE;
        break;
    }
    /* 获取互斥锁 */
    if (mutex_lock_interruptible(&pctrl->lock)) {
        dev_err(pctrl->dev, "Acquire %s %s mutex failed", __func__, pctrl->name);
        return -ERESTARTSYS;
    }
    pdev->range = range_code;
    val = pctrl->read_reg(pctrl->pcie_dev, AI_RANGE_OFFSET);
    // val &= (~(AI_RANGE_MASK << pdev->index));
    // val |= (pdev->range << pdev->index);
    val &= (~(AI_RANGE_MASK << pctrl->id[pdev->index]));
    val |= (pdev->range << pctrl->id[pdev->index]);
    pctrl->write_reg(pctrl->pcie_dev, AI_RANGE_OFFSET, val);
    dev_dbg(pdev->dev, "Set AI%d range success", pdev->index);
    /* 配置 AI 参数 */
    config_ai_nolock(pctrl);
    /* 释放互斥锁 */
    mutex_unlock(&pctrl->lock);

    return 0;
}

/* 获取 AI 量程 */
static int get_ai_range(struct ai_dev_t *pdev)
{
    struct ai_ctrl_t *pctrl = (struct ai_ctrl_t *)(pdev->parent);
    int ret = 0;
    u32 val = 0;

    /* 获取互斥锁 */
    if (mutex_lock_interruptible(&pctrl->lock)) {
        dev_err(pctrl->dev, "Acquire %s %s mutex failed", __func__, pctrl->name);
        return -ERESTARTSYS;
    }
    val = pctrl->read_reg(pctrl->pcie_dev, AI_RANGE_OFFSET);
    pdev->chk_range = ((val >> pctrl->id[pdev->index]) & AI_RANGE_MASK);
    if (pdev->chk_range != pdev->range) {
        dev_err(pdev->dev, "Get AI%d range %d, not the set %d", pdev->index, pdev->chk_range, pdev->range);
        ret = -EFAULT;
        goto unlock;
    } else {
        switch (pdev->chk_range) {
        case AI_RANGE_2V5:
            dev_dbg(pdev->dev, "Get AI%d range %s %d, is the set %d", 
                    pdev->index, "2.5V", pdev->chk_range, pdev->range);
            break;
        case AI_RANGE_5V:
            dev_dbg(pdev->dev, "Get AI%d range %s %d, is the set %d", 
                    pdev->index, "5V", pdev->chk_range, pdev->range);
            break;
        case AI_RANGE_10V0:
        case AI_RANGE_10V:
            dev_dbg(pdev->dev, "Get AI%d range %s %d, is the set %d", 
                    pdev->index, "10V", pdev->chk_range, pdev->range);
            break;
        default:
            dev_err(pdev->dev, "Get AI%d range %d not support", 
                     pdev->index, pdev->chk_range);
            break;
        }
    }

unlock:
    /* 释放互斥锁 */
    mutex_unlock(&pctrl->lock);

    return ret;
}

/* 获取 AI 指令 */
static int get_ai_cmd(struct ai_ctrl_t *pctrl)
{
    int ret = 0;
    u32 val = 0;

    /* 获取互斥锁 */
    if (mutex_lock_interruptible(&pctrl->lock)) {
        dev_err(pctrl->dev, "Acquire %s %s mutex failed", __func__, pctrl->name);
        return -ERESTARTSYS;
    }
    val = pctrl->read_reg(pctrl->pcie_dev, AI_CMD_OFFSET);
    pctrl->chk_cmd = ((val & AI_CMD_CODE_MASK) >> AI_CMD_CODE_SHIFT);
    if (pctrl->chk_cmd != pctrl->cmd) {
        dev_err(pctrl->dev, "Get AI cmd %d, not the set %d", 
                pctrl->chk_cmd, pctrl->cmd);
        ret = -EFAULT;
        goto unlock;
    } else {
        dev_dbg(pctrl->dev, "Get AI cmd %d, is the set %d", 
                pctrl->chk_cmd, pctrl->cmd);
    }

unlock:
    /* 释放互斥锁 */
    mutex_unlock(&pctrl->lock);

    return ret;
}

/* 获取 AI 数据 */
static s32 get_ai_val(struct ai_dev_t *pdev)
{
    struct ai_ctrl_t *pctrl = (struct ai_ctrl_t *)(pdev->parent);
    u32 u32_val = 0;
    s32 s32_val = 0;
    u8 i = 0;
    u8 start = 0;
    u8 end = 0;

    /* 获取互斥锁 */
    if (mutex_lock_interruptible(&pctrl->lock)) {
        dev_err(pctrl->dev, "Acquire %s %s mutex failed", __func__, pctrl->name);
        return -ERESTARTSYS;
    }
    if (pctrl->mode == AI_MOD_SMP_TIM) {
        start = 0;
        end = pctrl->num;
    } else {
        start = pdev->index;
        end = pdev->index + 1;
    }

    for (i = start; i < end; i++) {
        u32_val = 0;
        u32_val &= AI_ID_MASK;
        u32_val |= (pctrl->id[i] << AI_ID_SHIFT);
        pctrl->write_reg(pctrl->pcie_dev, AI_CH_VAL_OFFSET, u32_val);
        u32_val = pctrl->read_reg(pctrl->pcie_dev, AI_CH_VAL_OFFSET);
        s32_val = (s32)(u32_val & AI_DATA_MASK);
        /* 24bit 有符号数据转换为 32bit 有符号数据 */
        if ((s32_val & AI_DATA_SIGN_MASK) == AI_DATA_SIGN_MASK) {
            s32_val |= (~AI_DATA_MASK);
        }
        dev_dbg(pdev->dev, "Get AI%d u32=0x%08x s32=0x%08x %d", i, u32_val, s32_val, s32_val);
        s32_val /= pctrl->slid_win;
        switch (pdev->range) {
        case AI_RANGE_2V5:
            s32_val *= AI_RANGE_2V5_LSB;
            dev_dbg(pdev->dev, "Get AI%d=%duV(2.5V)", i, s32_val);
            break;
        case AI_RANGE_5V:
            s32_val *= AI_RANGE_5V_LSB;
            dev_dbg(pdev->dev, "Get AI%d=%duV(5V)", i, s32_val);
            break;
        case AI_RANGE_10V0:
        case AI_RANGE_10V:
            s32_val *= AI_RANGE_10V_LSB;
            dev_dbg(pdev->dev, "Get AI%d=%duV(10V)", i, s32_val);
            break;
        default:
            dev_warn(pdev->dev, "Get AI%d=%duV(range error)", i, s32_val);
            break;
        }
        pctrl->val[i] = s32_val;
    }
    /* 释放互斥锁 */
    mutex_unlock(&pctrl->lock);

    return s32_val;
}

// /* 获取 FPGA 版本号 */
// static u32 get_ai_fpga_ver_nolock(struct ai_ctrl_t *pctrl)
// {
//     pctrl->fpga_ver = pctrl->read_reg(pctrl->pcie_dev, AI_VERSION_OFFSET);
//     dev_dbg(pctrl->dev, "Get AI PPGA version 0x%08x", pctrl->fpga_ver);

//     return pctrl->fpga_ver;
// }

/* 打开设备 */
static int open_ai(struct inode *inode, struct file *filp)
{
    /* 获取与 inode 关联的字符设备 */
    struct cdev_dev_t *cdev_dev = container_of(inode->i_cdev, struct cdev_dev_t, cdev);
    struct cdev_ctrl_t *cdev_ctrl = (struct cdev_ctrl_t *)(cdev_dev->parent);
    struct ai_ctrl_t *pctrl = (struct ai_ctrl_t *)(cdev_ctrl->parent);
    struct ai_dev_t *priv = &pctrl->ai[cdev_dev->index];

    /* 检查设备是否有效 */
    if (!priv || !priv->dev) {
        pr_err("Invalid parameters for %s", __func__);
        return -ENODEV;
    }
    /* 记录设备指针 */
    filp->private_data = priv;
    /* 获取互斥锁 */
    if (mutex_lock_interruptible(&priv->lock)) {
        dev_err(priv->dev, "Acquire %s mutex failed", cdev_dev->name);
        return -ERESTARTSYS;
    }
    dev_info(priv->dev, "Open %s%d device", cdev_ctrl->name, cdev_dev->index);

    mutex_unlock(&priv->lock);

    return 0;
}

/* 关闭设备 */
static int release_ai(struct inode *inode, struct file *filp)
{
    struct ai_dev_t *priv = filp->private_data;
    struct ai_ctrl_t *pctrl = (struct ai_ctrl_t *)(priv->parent);

    if (priv) {
        mutex_lock(&priv->lock);
        dev_info(pctrl->dev, "cpl_cnt=%d/%d.", pctrl->cpl_cnt, pctrl->cpl_all);
        dev_info(priv->dev, "Release %s device", priv->name);
        mutex_unlock(&priv->lock);
    }

    return 0;
}

/* 读取设备 */
static ssize_t read_ai(struct file *filp, char __user *buf, 
                       size_t count, loff_t *ppos)
{
    struct ai_dev_t *priv = filp->private_data;
    struct ai_ctrl_t *pctrl = (struct ai_ctrl_t *)(priv->parent);
    ssize_t ret = 0;
    size_t read_len = 0;
    unsigned long flags;    /* 用于保存中断状态 */

    /* 检查参数是否有效 */
    if (!priv || !priv->dev || !buf) {
        pr_err("Invalid parameters for %s", __func__);
        return -ENODEV;
    }

    /* 检查偏移量是否有效 */
    if (*ppos > pctrl->dma.pl_size) {
        dev_err(priv->dev, "Beyond buffer size, pos=%lld, size=%zu", 
                *ppos, pctrl->dma.pl_size);
        return -EFBIG;
    } else if (*ppos == pctrl->dma.pl_size) {
        *ppos = 0;
    }

    /* 计算实际可读取长度 */
    read_len = min(count, (size_t)(pctrl->dma.pl_size - *ppos));

    switch (pctrl->mode) {
    case AI_MOD_RAW_DMA:
        /* 等待DMA帧完成（中断唤醒） */
        if (wait_event_interruptible(pctrl->dma.wq_frame, pctrl->dma.frame_done)) {
            dev_err(priv->dev, "Wait %s read data interrupted", priv->name);
            return -ERESTARTSYS;
        }
        pctrl->dma.frame_done = false;

        /* 获取互斥锁 */
        if (mutex_lock_interruptible(&priv->lock)) {
            dev_err(priv->dev, "Acquire %s mutex failed", priv->name);
            return -ERESTARTSYS;
        }

        /* 获取自旋锁(保存中断状态) */
        spin_lock_irqsave(&pctrl->dma.frame_lock, flags);
        /* 从DMA内存复制数据到用户空间 */
        if (copy_to_user(buf, pctrl->dma.alloc_virt + *ppos, read_len)) {
            /* 释放自旋锁(恢复中断状态) */
            spin_unlock_irqrestore(&pctrl->dma.frame_lock, flags);
            dev_err(priv->dev, "Copy %s %zu data to user space failed", priv->name, read_len);
            goto unlock;
        }
        pctrl->cpl_cnt--;
        pctrl->dma.frame_tail = (pctrl->dma.frame_tail + pctrl->dma.frame_size) % pctrl->dma.pl_size;
        /* 释放自旋锁(恢复中断状态) */
        spin_unlock_irqrestore(&pctrl->dma.frame_lock, flags);
        break;
    default:
        break;
    }

    dev_dbg(priv->dev, "Read %s %zu data from offset %lld", 
            priv->name, read_len, *ppos);
    /* 更新文件位置 */
    *ppos += read_len;
    ret = read_len;

unlock:
    mutex_unlock(&priv->lock);

    return ret;
}

/* 写入设备 */
static ssize_t write_ai(struct file *filp, const char __user *buf, 
                          size_t count, loff_t *ppos)
{
    struct ai_dev_t *priv = filp->private_data;
    struct ai_ctrl_t *pctrl = (struct ai_ctrl_t *)(priv->parent);
    ssize_t ret = 0;
    size_t write_len = 0;
    unsigned long flags;    /* 用于保存中断状态 */

    /* 检查参数是否有效 */
    if (!priv || !priv->dev || !buf) {
        pr_err("Invalid parameters for %s", __func__);
        return -ENODEV;
    }

    /* 检查偏移量是否有效 */
    if (*ppos > pctrl->dma.pl_size) {
        dev_err(priv->dev, "Beyond buffer size, pos=%lld, size=%zu", 
                *ppos, pctrl->dma.pl_size);
        return -EFBIG;
    } else if (*ppos == pctrl->dma.pl_size) {
        *ppos = 0;
    }

    /* 计算实际写入取长度 */
    write_len = min(count, (size_t)(pctrl->dma.pl_size - *ppos));

    /* 获取互斥锁 */
    if (mutex_lock_interruptible(&priv->lock)) {
        dev_err(priv->dev, "Acquire %s mutex failed", priv->name);
        return -ERESTARTSYS;
    }

    /* 获取自旋锁(保存中断状态) */
    spin_lock_irqsave(&pctrl->dma.frame_lock, flags);
    /* 从用户空间复制到内核空间 */
    if (copy_from_user(pctrl->dma.alloc_virt + *ppos, buf, write_len)) {
        /* 释放自旋锁(恢复中断状态) */
        spin_unlock_irqrestore(&pctrl->dma.frame_lock, flags);
        dev_err(priv->dev, "Copy %s %zu data from user space failed", priv->name, write_len);
        ret = -EFAULT;
        goto unlock;
    }
    pctrl->cpl_cnt--;
    pctrl->dma.frame_tail = (pctrl->dma.frame_tail + pctrl->dma.frame_size) % pctrl->dma.pl_size;
    /* 释放自旋锁(恢复中断状态) */
    spin_unlock_irqrestore(&pctrl->dma.frame_lock, flags);

    dev_dbg(priv->dev, "Write %s %zu data to offset %lld", 
            priv->name, write_len, *ppos);
    /* 更新文件位置 */
    *ppos += write_len;
    ret = write_len;

unlock:
    mutex_unlock(&priv->lock);

    return ret;
}

/* IOCTL 处理 */
static long ioctl_ai(struct file *filp, unsigned int cmd, 
                          unsigned long arg)
{
    struct ai_dev_t *priv = filp->private_data;
    struct ai_ctrl_t *pctrl = (struct ai_ctrl_t *)(priv->parent);
    long ret = 0;
    u8 u8_val = 0;
    u16 u16_val = 0;
    u32 u32_val = 0;
    s32 s32_val = 0;
    // struct ai_buf_t buf;

    /* 检查参数是否有效 */
    if (!priv || !priv->dev) {
        pr_err("Invalid parameters for %s", __func__);
        return -ENODEV;
    }

    /* 获取互斥锁 */
    if (mutex_lock_interruptible(&priv->lock)) {
        dev_err(priv->dev, "Acquire %s %s mutex failed", __func__, priv->name);
        return -ERESTARTSYS;
    }
    switch (cmd) {
    /* 配置 AI 模式 */
    case IOCTL_AI_SET_MODE:
        if (copy_from_user(&u8_val, (void __user *)arg, sizeof(u8_val))) {
            dev_err(priv->dev, "Set AI mode copy failed");
            ret = -EFAULT;
            goto unlock;
        }
        if (set_ai_mode(pctrl, u8_val) < 0) {
            dev_err(priv->dev, "Set AI mode %d failed", u8_val);
            ret = -EFAULT;
            goto unlock;
        }
        break;
    /* 获取 AI 模式 */
    case IOCTL_AI_CHK_MODE:
        if (get_ai_mode(pctrl) < 0) {
            dev_err(priv->dev, "Get AI mode %d failed", pctrl->chk_mode);
            ret = -EFAULT;
            goto unlock;
        }
        if (copy_to_user((void __user *)arg, &pctrl->chk_mode, sizeof(pctrl->chk_mode))) {
            dev_err(priv->dev, "Get AI mode %d copy failed", pctrl->chk_mode);
            ret = -EFAULT;
            goto unlock;
        }
        break;
    /* 配置 AI 过采样 */
    case IOCTL_AI_SET_OSR:
        if (copy_from_user(&u8_val, (void __user *)arg, sizeof(u8_val))) {
            dev_err(priv->dev, "Set AI OSR copy failed");
            ret = -EFAULT;
            goto unlock;
        }
        if (set_ai_osr(pctrl, u8_val) < 0) {
            dev_err(priv->dev, "Set AI OSR %d failed", u8_val);
            ret = -EFAULT;
            goto unlock;
        }
        break;
    /* 获取 AI 过采样 */
    case IOCTL_AI_CHK_OSR:
        if (get_ai_osr(pctrl) < 0) {
            dev_err(priv->dev, "Get AI OSR %d failed", pctrl->chk_mode);
            ret = -EFAULT;
            goto unlock;
        }
        if (copy_to_user((void __user *)arg, &pctrl->chk_osr, sizeof(pctrl->chk_osr))) {
            dev_err(priv->dev, "Get AI OSR %d copy failed", pctrl->chk_osr);
            ret = -EFAULT;
            goto unlock;
        }
        break;
    /* 配置 AI 采样率 */
    case IOCTL_AI_SET_SAMP_RATE:
        if (copy_from_user(&u32_val, (void __user *)arg, sizeof(u32_val))) {
            dev_err(priv->dev, "Set AI sample rate copy failed");
            ret = -EFAULT;
            goto unlock;
        }
        if (set_ai_samp_rate(pctrl, u32_val) < 0) {
            dev_err(priv->dev, "Set AI sample rate %dus failed", u32_val);
            ret = -EFAULT;
            goto unlock;
        }
        break;
    /* 获取 AI 采样率 */
    case IOCTL_AI_CHK_SAMP_RATE:
        if (get_ai_samp_rate(pctrl) < 0) {
            dev_err(priv->dev, "Get AI sample rate %d failed", pctrl->chk_samp_rate);
            ret = -EFAULT;
            goto unlock;
        }
        if (copy_to_user((void __user *)arg, &pctrl->chk_samp_rate, sizeof(pctrl->chk_samp_rate))) {
            dev_err(priv->dev, "Get AI sample rate %d copy failed", pctrl->chk_samp_rate);
            ret = -EFAULT;
            goto unlock;
        }
        break;
    /* 配置 AI 抽样定时间隔 */
    case IOCTL_AI_SET_IRQ_RATE:
        if (copy_from_user(&u16_val, (void __user *)arg, sizeof(u16_val))) {
            dev_err(priv->dev, "Set AI sample time failed");
            ret = -EFAULT;
            goto unlock;
        }
        if (set_ai_samp_tim(pctrl, u16_val) < 0) {
            dev_err(priv->dev, "Set AI sample time %dus failed", u16_val);
            ret = -EFAULT;
            goto unlock;
        }
        break;
    /* 获取 AI 抽样定时间隔 */
    case IOCTL_AI_CHK_IRQ_RATE:
        if (get_ai_samp_tim(pctrl) < 0) {
            dev_err(priv->dev, "Get AI sample time %d failed", pctrl->chk_samp_tim);
            ret = -EFAULT;
            goto unlock;
        }
        if (copy_to_user((void __user *)arg, &pctrl->chk_samp_tim, sizeof(pctrl->chk_samp_tim))) {
            dev_err(priv->dev, "Get AI sample time %d copy failed", pctrl->chk_samp_tim);
            ret = -EFAULT;
            goto unlock;
        }
        break;
    /* 配置 AI 滑动平均窗口 */
    case IOCTL_AI_SET_SLID_WIN:
        if (copy_from_user(&u16_val, (void __user *)arg, sizeof(u16_val))) {
            dev_err(priv->dev, "Set AI slide window failed");
            ret = -EFAULT;
            goto unlock;
        }
        if (set_ai_slid_win(pctrl, u16_val) < 0) {
            dev_err(priv->dev, "Set AI slide window %d failed", u16_val);
            ret = -EFAULT;
            goto unlock;
        }
        break;
    /* 获取 AI 滑动平均窗口 */
    case IOCTL_AI_CHK_SLID_WIN:
        if (get_ai_slid_win(pctrl) < 0) {
            dev_err(priv->dev, "Get AI slide window %d failed", pctrl->chk_slid_win);
            ret = -EFAULT;
            goto unlock;
        }
        if (copy_to_user((void __user *)arg, &pctrl->chk_slid_win, sizeof(pctrl->chk_slid_win))) {
            dev_err(priv->dev, "Get AI slide window %d copy failed", pctrl->chk_slid_win);
            ret = -EFAULT;
            goto unlock;
        }
        break;
    /* 配置 AI 量程 */
    case IOCTL_AI_SET_RANGE:
        if (copy_from_user(&u8_val, (void __user *)arg, sizeof(u8_val))) {
            dev_err(priv->dev, "Set AI%d range copy failed", priv->index);
            ret = -EFAULT;
            goto unlock;
        }
        if (set_ai_range(priv, u8_val) < 0) {
            dev_err(priv->dev, "Set AI%d range %d failed", priv->index, u8_val);
            ret = -EFAULT;
            goto unlock;
        }
        break;
    /* 获取 AI 量程 */
    case IOCTL_AI_CHK_RANGE:
        if (get_ai_range(priv) < 0) {
            dev_err(priv->dev, "Get AI%d range %d failed", priv->index, priv->chk_range);
            ret = -EFAULT;
            goto unlock;
        }
        if (copy_to_user((void __user *)arg, &priv->chk_range, sizeof(priv->chk_range))) {
            dev_err(priv->dev, "Get AI%d range %d copy failed", priv->index, priv->chk_range);
            ret = -EFAULT;
            goto unlock;
        }
        break;
    /* 获取 AI 数值 */
    case IOCTL_AI_GET_VAL:
        /* 获取 AI 数据 */
        s32_val = get_ai_val(priv);
        if (copy_to_user((void __user *)arg, &s32_val, sizeof(s32_val))) {
            dev_err(priv->dev, "Get AI%d=%duV copy failed", priv->index, pctrl->val[priv->index]);
            ret = -EFAULT;
            goto unlock;
        }
        break;
    /* 等待 AI 定时中断 */
    case IOCTL_AI_WAIT_TIM_IRQ:
        /* 检查指针是否效性 */
#if LINUX_VERSION_CODE >= KERNEL_VERSION(5,10,0)
        /* 新版本 kernel：access_ok(addr, size) */
        if (!access_ok((void __user *)arg, pctrl->num * sizeof(s32))) {
            dev_err(priv->dev, "Get AI%d value, invalid user buffer pointer %p", priv->index, (void __user *)arg);
            ret = -EFAULT;
            goto unlock;
        }
#else
        /* 老版本 kernel：access_ok(type, addr, size) */
        if (!access_ok(VERIFY_WRITE, (void __user *)arg, pctrl->num * sizeof(s32))) {
            dev_err(priv->dev, "Get AI%d value, invalid user buffer pointer %p", priv->index, (void __user *)arg);
            ret = -EFAULT;
            goto unlock;
        }
#endif
        switch (pctrl->mode) {
        case AI_MOD_SMP_TIM:
            mutex_unlock(&priv->lock);
            dev_dbg(priv->dev, "Wait %s time irq...", priv->name);
            /* 等待 定时器 等待队列(可中断唤醒) */
            if (wait_event_interruptible(pctrl->tim_wq, pctrl->is_tim_irq)) {
                dev_err(priv->dev, "Wait %s event interrupted", priv->name);
                return -ERESTARTSYS;
            }
            pctrl->is_tim_irq = false;
            dev_dbg(priv->dev, "Capture %s time irq", priv->name);
            /* 获取互斥锁 */
            if (mutex_lock_interruptible(&priv->lock)) {
                dev_err(priv->dev, "Acquire %s mutex failed", priv->name);
                return -ERESTARTSYS;
            }
            /* 获取 AI 数据 */
            get_ai_val(priv);
            if (copy_to_user((void __user *)arg, &pctrl->val[0], pctrl->num * sizeof(s32))) {
                dev_err(priv->dev, "Get AI value copy failed");
                ret = -EFAULT;
                goto unlock;
            }
            break;
        default:
            /* 获取 AI 数据 */
            get_ai_val(priv);
            if (copy_to_user((void __user *)arg, &pctrl->val[priv->index], 1 * sizeof(s32))) {
                dev_err(priv->dev, "Get AI%d=%duV copy failed", priv->index, pctrl->val[priv->index]);
                ret = -EFAULT;
                goto unlock;
            }
            break;
        }
        break;
    /* 开始 AI 采集 */
    case IOCTL_AI_START:
        start_ai_nolock(pctrl);
        break;
    /* 停止 AI 采集 */
    case IOCTL_AI_STOP:
        stop_ai_nolock(pctrl);
        break;
    /* 获取 AI 量程 */
    case IOCTL_AI_CHK_CMD:
        if (get_ai_cmd(pctrl) < 0) {
            dev_err(pctrl->dev, "Get AI cmd %d failed", pctrl->chk_cmd);
            ret = -EFAULT;
            goto unlock;
        }
        if (copy_to_user((void __user *)arg, &pctrl->chk_cmd, sizeof(pctrl->chk_cmd))) {
            dev_err(pctrl->dev, "Get AI cmd %d copy failed", pctrl->chk_cmd);
            ret = -EFAULT;
            goto unlock;
        }
        break;
    /* 获取驱动版本号 */
    case IOCTL_AI_GET_DRV_VERSION:
        if (copy_to_user((void __user *)arg, &pctrl->drv_ver, sizeof(pctrl->drv_ver))) {
            dev_err(pctrl->dev, "Get AI driver version %d copy failed", pctrl->drv_ver);
            ret = -EFAULT;
            goto unlock;
        }
        break;
    /* 获取 FPGA 版本号 */
    case IOCTL_AI_GET_FPGA_VERSION:
        if (copy_to_user((void __user *)arg, &pctrl->fpga_ver, sizeof(pctrl->fpga_ver))) {
            dev_err(pctrl->dev, "Get AI FPGA version %d copy failed", pctrl->fpga_ver);
            ret = -EFAULT;
            goto unlock;
        }
        break;
    default:
        dev_err(priv->dev, "Ioctl AI%d cmd=0x%08x, dir=0x%X, size=%u, type=0x%02X('%c'), nr=%u not support\n",
                priv->index, cmd, _IOC_DIR(cmd), _IOC_SIZE(cmd), _IOC_TYPE(cmd), _IOC_TYPE(cmd), _IOC_NR(cmd));
        ret = -ENOTTY;
        break;
    }

unlock:
    mutex_unlock(&priv->lock);

    return ret;
}

/* AI 定时中断 */
static irqreturn_t ai_tim_interrupt(int irq, void *dev_id)
{
    struct ai_dev_t *priv = dev_id;
    struct ai_ctrl_t *pctrl = (struct ai_ctrl_t *)(priv->parent);

    if (!priv || !priv->dev || !pctrl) {
        pr_err("Invalid parameters for %s, %p, %p, %p", 
               __func__, priv, priv->dev, pctrl);
        return IRQ_NONE;
    }
    dev_dbg(priv->dev, "IRQ: %s irq=%d", priv->name, irq);

    /* 禁用 MSI 中断 */
    disable_ai_msi_irq(pctrl);
    pctrl->is_tim_irq = true;
    wake_up_interruptible(&pctrl->tim_wq);       /* 唤醒等待队列 */
    /* 使能 MSI 中断 */
    enable_ai_msi_irq(pctrl);

    return IRQ_HANDLED;
}

/* AI DMA 中断 */
static irqreturn_t ai_dma_interrupt(int irq, void *dev_id)
{
    struct ai_dev_t *priv = dev_id;
    struct ai_ctrl_t *pctrl = (struct ai_ctrl_t *)(priv->parent);

    if (!priv || !priv->dev) {
        pr_err("Invalid parameters for %s", __func__);
        return IRQ_NONE;
    }
    // dev_dbg(priv->dev, "IRQ: %s irq=%d", priv->name, irq);

    /* 禁用 MSI 中断 */
    // disable_ai_msi_irq(pctrl);
    /* 中断内调度工作队列 */
    if(false == schedule_work(&pctrl->dma_irq_work)) {
        dev_info(priv->dev, "dma schedule_work failed!");
    }
    /* 使能 MSI 中断 */
    // enable_ai_msi_irq(pctrl);

    return IRQ_HANDLED;
}

/* 工作队列处理函数(中断下半部) */
static void dma_work_queue_handler(struct work_struct *work_queue)
{
    struct ai_ctrl_t *pctrl = container_of(work_queue, struct ai_ctrl_t, dma_irq_work);
    struct pcie_dma_t *dma = &pctrl->dma;
    u32 i = 0;
    // u32 daq_acquire = 0;
    unsigned long flags;    /* 用于保存中断状态 */

    /* 这里执行需要在进程上下文中处理的任务 */
    pctrl->cpl_cnt++;
    pctrl->cpl_all++;
    // dev_info(pctrl->dev, "cpl_cnt=%d/%d.", pctrl->cpl_cnt, pctrl->cpl_all);
    for (i = 0; i < (dma->frame_size / dma->pkt_len); i++) {
        /* 开始 PCIe DMA 传输 */
        if (0 == start_pcie_dma(dma)) {
            /* 更新 PCIe DMA 地址 */
            update_pcie_dma_addr(dma);
        }
    }
    /* 环形缓冲区指针操作, 自旋锁保护*/
    spin_lock_irqsave(&dma->frame_lock, flags);    /* 获取自旋锁（保存中断状态） */
    // memcpy(&daq_acquire, (const u8 *)pctrl->dma.alloc_virt + dma->frame_head + 10, sizeof(daq_acquire));
    dma->frame_head = (dma->frame_head + dma->frame_size) % dma->pl_size;
    /* 缓冲区已满 */
    if (dma->frame_head == dma->frame_tail) {
        /* 丢弃最旧数据 */
        dma->frame_tail = (dma->frame_tail + dma->frame_size) % dma->pl_size;
    } else {
        /* 缓冲区有新数据 */
        dma->frame_done = true;
        wake_up_interruptible(&dma->wq_frame);     /* 唤醒等待队列（数据帧完成） */
        dma->frame_cnt = ((dma->frame_cnt + 1) % (dma->pl_size / dma->frame_size));
    }
    spin_unlock_irqrestore(&dma->frame_lock, flags);    /* 释放自旋锁（恢复中断状态） */
    // dev_info(pctrl->dev, "daq_acquire=%d", daq_acquire);
    // dev_dbg(pctrl->dev, "AI interrupt handled.");
    /* 注意：在这个函数中, 可以安全地调用可能睡眠的函数 */
}

/* 初始化 AI 设备 */
static int init_ai_dev(void *parent, struct device *dev, const char *name, 
                       struct ai_dev_t *ai, u8 index, u8 range)
{
    int ret = 0;

    ai->parent = parent;
    ai->dev = dev;
    /* 初始化互斥锁 */
    mutex_init(&ai->lock);
    strscpy(ai->name, name, sizeof(ai->name));
    ai->index = index;

    ai->range = range;
    /* 配置 AI 量程 */
    set_ai_range(ai, range);

    return ret;
}

/* 初始化 AI 控制器 */
int init_ai_ctrl(struct pcie_dev_t *pcie_dev, struct cdev_dev_t *cdev_dev, 
                 struct ai_ctrl_t *pctrl, struct ai_dev_t *ai, 
                 const char *ctrl_name, u8 dev_num, u8 type)
{
    int ret = 0;
    int i = 0;
    char name[32];

    pctrl->dev = &pcie_dev->pdev->dev;
    /* 初始化互斥锁 */
    mutex_init(&pctrl->lock);
    snprintf(pctrl->name, sizeof(pctrl->name), "%s", ctrl_name);
    pctrl->num = dev_num;
    pctrl->pcie_dev = pcie_dev;
    pctrl->read_reg = read_ai_reg_le;
    pctrl->write_reg = write_ai_reg_le;
    pctrl->cdev_ctrl.cdev_dev = cdev_dev;
    pctrl->pkt_size = AI_DEF_DMA_SIZE;
    pctrl->cpl_cnt = 0;
    pctrl->cpl_all = 0;
    pctrl->ai = ai;
    pctrl->type = type;
    switch (type) {
    case AI_TYPE_AC:
        pctrl->id[0] = 0;
        pctrl->id[1] = 1;
        pctrl->id[2] = 2;
        pctrl->id[3] = 3;
        pctrl->id[4] = 4;
        pctrl->id[5] = 5;
        pctrl->id[6] = 8;
        pctrl->id[7] = 9;
        pctrl->id[8] = 10;
        break;
    case AI_TYPE_PT100:
    case AI_TYPE_AI:
    default:
        for (i = 0; i < dev_num; i++) {
            pctrl->id[i] = i;
        }
        break;
    }
    pctrl->drv_ver = CDEV_DRV_VERSION(AI_VER_MAJOR, AI_VER_MINOR, AI_VER_PATCH);
    pctrl->fpga_ver = pcie_dev->read_mem(pcie_dev->bar[0] + AI_VERSION_OFFSET);

    /* 初始化 定时器 等待队列 */
    init_waitqueue_head(&pctrl->tim_wq);
    /* 初始化工作队列 */
    INIT_WORK(&pctrl->dma_irq_work, dma_work_queue_handler);

    /* 初始化中断 */
    enable_ai_msi_irq(pctrl);
    // enable_ai_dma_msi_irq(pctrl);
    pctrl->tim_irq.irq = &pcie_irq;
    ret = init_pcie_irq(pctrl->pcie_dev->pdev, &pctrl->tim_irq, 
                        PCI_IRQ_MSI, AI_TIM_MSI_VEC, AI_TIM_MSI_VEC, 
                        ai_tim_interrupt, pctrl->name,
                        pctrl->ai, sizeof(struct ai_dev_t), pctrl->pcie_dev->bar[0]);
    if (ret) {
        dev_err(pctrl->dev, "Init %s pcie interrupt failed", pctrl->name);
        goto err_free_dev;
    }
    pctrl->dma_irq.irq = &pcie_irq;
    ret = init_pcie_irq(pctrl->pcie_dev->pdev, &pctrl->dma_irq, 
                        PCI_IRQ_MSI, AI_DMA_MSI_VEC, AI_DMA_MSI_VEC, 
                        ai_dma_interrupt, pctrl->name,
                        pctrl->ai, sizeof(struct ai_dev_t), pctrl->pcie_dev->bar[0]);
    if (ret) {
        dev_err(pctrl->dev, "Init %s pcie interrupt failed", pctrl->name);
        goto err_cleanup_tim_irq;
    }

    /* 初始化字符设备 */
    ret = init_cdev_ctrl(pctrl, &pctrl->cdev_ctrl, pctrl->name, dev_num);
    if (ret < 0) {
        dev_err(pctrl->dev, "Init %s controller failed", pctrl->name);
        goto err_cleanup_irq;
        // goto err_free_dev;
    }
    for (i = 0; i < dev_num; i++) {
        snprintf(name, sizeof(name), "%s%d", pctrl->name, i);
        ret = init_cdev_dev(&pctrl->cdev_ctrl, pctrl->cdev_ctrl.cclass, 
                            &pctrl->cdev_ctrl.cdev_dev[i], &cdev_fops, pctrl->cdev_ctrl.major_devno, name, i);
        if (ret) {
            dev_err(pctrl->dev, "Init %s device failed", name);
            goto err_cleanup_cdev_ctrl;
        }
    }

    /* 初始化 AI 设备*/
    set_ai_mode(pctrl, AI_DEF_MODE);                /* 配置 AI 模式 */
    set_ai_osr(pctrl, AI_DEF_OSR);                  /* 配置 AI 过采样 */
    set_ai_samp_rate(pctrl, AI_DEF_SAMPLE);         /* 配置 AI 采样间隔时间 */
    set_ai_samp_tim(pctrl, AI_DEF_SAMP_TIM);        /* 配置 AI 抽样定时间隔 */
    set_ai_slid_win(pctrl, AI_DEF_SLID_WIN);        /* 配置 AI 滑动平均窗口 */
    for (i = 0; i < dev_num; i++) {
        init_ai_dev(pctrl, pctrl->dev, pctrl->cdev_ctrl.cdev_dev[i].name, 
                    &pctrl->ai[i], i, AI_DEF_RANGE);
    }

    return 0;

err_cleanup_cdev_ctrl:
    exit_cdev_ctrl(&pctrl->cdev_ctrl);
err_cleanup_irq:
    exit_pcie_irq(&pctrl->dma_irq, pctrl->ai, sizeof(struct ai_dev_t));
err_cleanup_tim_irq:
    exit_pcie_irq(&pctrl->tim_irq, pctrl->ai, sizeof(struct ai_dev_t));
err_free_dev:

    return ret;
}

/* 注销 AI 控制器 */
void exit_ai_ctrl(struct ai_ctrl_t *pctrl, u8 dev_num)
{
    u8 i = 0;

    if (!pctrl) {
        pr_err("Invalid parameters for %s", __func__);
        return;
    }

    for (i = 0; i < dev_num; i++) {
        exit_cdev_dev(pctrl->cdev_ctrl.cclass, &pctrl->cdev_ctrl.cdev_dev[i]);
    }
    exit_cdev_ctrl(&pctrl->cdev_ctrl);
    dev_info(pctrl->dev, "Release cdev controller success");

    exit_pcie_irq(&pctrl->tim_irq, pctrl->ai, sizeof(struct ai_dev_t));
    exit_pcie_irq(&pctrl->dma_irq, pctrl->ai, sizeof(struct ai_dev_t));
    dev_info(pctrl->dev, "Release irq controller success");

    for (i = 0; i < dev_num; i++) {
        mutex_destroy(&pctrl->ai[i].lock);
    }
    /* 注销互斥锁 */
    mutex_destroy(&pctrl->lock);

    dev_info(pctrl->dev, "PCIe character device %s removed", pctrl->name);
}
